
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <cmath>

#include <cereal/types/memory.hpp>
#include <cereal/archives/binary.hpp>
#include <cereal/archives/json.hpp>
#include <cereal/types/vector.hpp>
#include <cereal/types/string.hpp>
#include <cereal/types/unordered_map.hpp>
#include <cereal/types/tuple.hpp>

using namespace std;

namespace llll {


template<typename ... Args>
std::string ssserialize(const Args& ... _args) {
    std::tuple<Args...> _params(_args...);
    std::ostringstream os;
    cereal::BinaryOutputArchive arch(os);
    arch(_params);
    return os.str();
}

template<typename T>
T ssdeserialize(const char* _buf) {
    T ans;
    std::istringstream is(_buf);
    cereal::BinaryInputArchive arch(is);
    arch(ans);
    return ans;
}

std::string _cl;

struct MyRecord {
    int32_t x = 0;
    int32_t y = 0;
    float_t z = 0.0;

    std::string name;

    std::vector<std::string> cs;

    MyRecord() = default;

    MyRecord(int32_t _x, int32_t _y, float_t _z, std::string _n, std::vector<std::string> _c)
            : x(_x), y(_y), z(_z), name(std::move(_n)), cs(std::move(_c)) {}

    template<typename Arch>
    void serialize(Arch &_arch) {
        _arch(x, y, z, name, cs);
    }
};

struct MyData {
    int id = 0;
    std::unordered_map<int, MyRecord> ds;

    template<typename Arch>
    void serialize(Arch &_arch) {
        _arch(id, ds);
    }
};


std::string sssss(const MyData& _md) {
    std::tuple<MyData> _params(_md);
    std::ostringstream os;
    cereal::BinaryOutputArchive arch(os);
    arch(_params);
    return os.str();
}

MyData ddddd(const string& _s) {
    MyData ans;
    std::istringstream is(_s);
    cereal::BinaryInputArchive arch(is);
    cout << "8888*****" << is.str().size() << endl;
    arch(ans);
    return ans;
}

void test001() {
    MyData data{
            132,
            {
                    {12, {1, 2, 3, "Tom Cris", {"dsdsds", "212121", "cxcxcx"}}},
                    {13, {4, 5, 6, "Alex Mullen", {"545454", "gfgfgf", "l;"}}},
                    {20, {7, 8, 9, "Mark Alen", {"gf"}}}
            }
    };

    cout << "================== show data ======================" << endl;
    std::cout << data.id << std::endl;
    for (auto &[k, v]: data.ds) {
        std::cout << k << ": " << v.x << ' ' << v.y << ' ' << v.z << v.name << ' ';
        for (auto &c: v.cs) std::cout << c << ' ';
        std::cout << std::endl;
    }
    std::cout << std::endl;

    cout << "serializing" << endl;
    std::string _ss = sssss(data);
    _cl = _ss;
    cout << "finished" << endl;
}

void test002() {
    cout << "deserializing" << endl;
    auto md = ddddd(_cl);
    cout << "finished" << endl;

    std::cout << "==============serialized======================" << endl;
    std::cout << md.id << std::endl;
    for (auto &[k, v]: md.ds) {
        std::cout << k << ": " << v.x << ' ' << v.y << ' ' << v.z << v.name << ' ';
        for (auto &c: v.cs) std::cout << c << ' ';
        std::cout << std::endl;
    }
    std::cout << std::endl;
}

}

int main(int argc, char** argv) {

    llll::test001();

    llll::test002();

    return 0;
}
